package com.yungu.swift.api.route.v1.passenger;

import com.alibaba.dubbo.config.annotation.Reference;
import com.fasterxml.jackson.databind.JsonNode;
import com.yungu.swift.api.base.BaseApi;
import com.yungu.swift.api.utils.RandomUtil;
import com.yungu.swift.api.wxapi.WxConstants;
import com.yungu.swift.assets.passenger.model.dto.PassengerDto;
import com.yungu.swift.assets.passenger.model.dto.PassengerLogDto;
import com.yungu.swift.assets.passenger.model.vo.PassengerVo;
import com.yungu.swift.assets.passenger.service.PassengerService;
import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.common.model.dto.CommonIdentifyDto;
import com.yungu.swift.common.service.CommonSmsService;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.MagicConstant;
import com.yungu.swift.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;

/**
 * @author gred
 * @description
 * @date 2016/12/08. <br>
 */
@Slf4j
@Controller
@RequestMapping(value = "/api/v1/passenger")
@Api(value = "【乘客】【登录】乘客登陆接口", tags = "乘客登陆相关操作")
public class LoginApi extends BaseApi {

    private final Logger logger = LoggerFactory.getLogger(LoginApi.class);

    private static String user_access_token_url = " https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=APPSECRET&code=CODE&grant_type=authorization_code";
    @Reference
    private PassengerService passengerService;
    @Reference
    private CommonSmsService commonSmsService;
    @Autowired
    private RedisCacheService redisCacheService;


    @ApiOperation(value = "乘客登陆接口", notes = "返回成功或失败消息")
    @RequestMapping(value = {"/login/login"}, method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public ResponseData login(
            @ApiParam(name = "appid", value = "APP标识", required = true) @RequestParam String appid,
            @ApiParam(name = "mobile", value = "手机号", required = true) @RequestParam String mobile,
            @ApiParam(name = "identifyCode", value = "验证码", required = true) @RequestParam String identifyCode,
            @ApiParam(name = "nickName", value = "昵称") @RequestParam(value = "nickName", required = false) String nickName,
            @ApiParam(name = "sex", value = "性别(1男，2女)") @RequestParam(value = "sex", required = false) Integer sex,
            @ApiParam(name = "deviceType", value = "操作系统（1：android，2：IOS）") @RequestParam(value = "deviceType", required = false) Integer deviceType,
            @ApiParam(name = "deviceToken", value = "设备唯一标示") @RequestParam(value = "deviceToken", required = false) String deviceToken,
            @ApiParam(name = "deviceVersion", value = "操作系统版本号") @RequestParam(value = "deviceVersion", required = false) String deviceVersion,
            @ApiParam(name = "appVersion", value = "应用版本") @RequestParam(value = "appVersion", required = false) String appVersion,
            @ApiParam(name = "lng", value = "当前用户所在位置的经度") @RequestParam(value = "lng", required = false) Double lng,
            @ApiParam(name = "lat", value = "当前用户所在位置的纬度") @RequestParam(value = "lat", required = false) Double lat,
            @ApiParam(name = "openId", value = "微信openid") @RequestParam(value = "openId", required = false) String openId,
            @ApiParam(name = "ip", value = "用户端ip地址") @RequestParam(value = "ip", required = false) String ip,
            @ApiParam(name = "port", value = "用户端端口号") @RequestParam(value = "port", required = false) Integer port,
            @ApiParam(name = "mac", value = "用户端mac地址") @RequestParam(value = "mac", required = false) String mac,
            @ApiParam(name = "imei", value = "用户端IMEI") @RequestParam(value = "imei", required = false) String imei,
            @ApiParam(name = "hardSign", value = "硬件特征串") @RequestParam(value = "hardSign", required = false) String hardSign,
            @ApiParam(name = "countryMobileCode", value = "国家手机号前缀") @RequestParam(value = "countryMobileCode", required = false) String countryMobileCode,
            HttpServletRequest request) {
        String decryptMobile = RandomUtil.randomDecrypt(mobile);
        //判断电话是否准确
        if (!ValidateUtils.validateMobile(decryptMobile)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "请输入正确的手机号");
        }
        String decryptIdentifyCode = RandomUtil.randomDecrypt(identifyCode);
        if (decryptIdentifyCode.length() != MagicConstant.INT_FOUR) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "请输入正确的验证码");
        }
        //验证码限制三分钟只能输错5次
        int loginCount = 1;
        Object object = redisCacheService.get("PassengerLoginCount" + decryptMobile);
        if (object != null) {
            loginCount = (Integer) object;
        }
        if (loginCount > 5) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "已连续输错5次，3分钟内不允许登陆");
        }
        // 检验 验证码
        CommonIdentifyDto commonIdentifyDto = null;
        String mobileTop3 = decryptMobile.substring(0, 3);
        if (!mobileTop3.equals(MagicConstant.STRING_ONE_FOUR_TWO)) {
            Map<String, Object> paramMap = MapUtils.build(3);
            paramMap.put("mobile", decryptMobile);
            paramMap.put("identifyCode", decryptIdentifyCode);
            paramMap.put("status", CommonConstant.IDENTIFY_CODE_STATUS_UNUSED);
            paramMap.put("appid", appid);
            paramMap.put("type", "1");
            commonIdentifyDto = commonSmsService.get(paramMap).getData();
            if (commonIdentifyDto == null) {
                loginCount++;
                redisCacheService.set("PassengerLoginCount" + decryptMobile, loginCount, 3L);
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "验证码错误");
            }
            redisCacheService.delete("PassengerLoginCount" + decryptMobile);
            if (System.currentTimeMillis() - commonIdentifyDto.getCreateOn().getTime() > 120000) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "验证码已过期，请重新获取");
            }
        }
        //乘客相关信息
        PassengerLogDto passengerLog = new PassengerLogDto();
        passengerLog.setIp(getUserIP(request));
        passengerLog.setPort(request.getRemotePort());
        passengerLog.setMac(mac);
        passengerLog.setImei(imei);
        passengerLog.setHardwareSignature(hardSign);
        passengerLog.setLng(lng);
        passengerLog.setLat(lat);
        //乘客新增
        PassengerDto passenger = new PassengerDto();
        passenger.setMobile(decryptMobile);
        passenger.setNickname(nickName);
        passenger.setSex(sex);
        passenger.setDeviceType(deviceType);
        passenger.setDeviceToken(deviceToken);
        passenger.setDeviceVersion(deviceVersion);
        passenger.setAppVersion(appVersion);
        passenger.setOpenId(openId);
        passenger.setAppid(appid);
        passenger.setCountryMobileCode(countryMobileCode);
        // 设置为激活状态
        passenger.setActive(1);
        ResponseData<PassengerVo> login = passengerService.login(passenger, passengerLog);
        if (login.isSuccess() && login.getData() != null && commonIdentifyDto != null && !mobileTop3.equals(MagicConstant.STRING_ONE_FOUR_TWO)) {
            //用户的验证码设置为已使用
            commonIdentifyDto.setStatus(CommonConstant.IDENTIFY_CODE_STATUS_USED);
            //更新验证码
            commonSmsService.edit(commonIdentifyDto);
        }
        if(login.getData().getFace() !=null && !login.getData().getFace().contains("https")) {
            login.getData().setFace("https://swift.laobingchuxing01.com/imgs"+login.getData().getFace());
        }
        return login;
    }

    @ApiOperation(value = "乘客登出接口", notes = "返回成功或失败消息")
    @RequestMapping(value = {"/token/login/logout"}, method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public ResponseData<Boolean> logout(
            @ApiParam(name = "token", value = "token", required = true) @RequestParam String token,
            @ApiParam(name = "appid", value = "APP标识", required = true) @RequestParam String appid) {

        //判断token是否为空
        if (StringUtils.isEmpty(token)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "token不能为空", null);
        }
        return passengerService.logout(token, appid);
    }

    @ApiOperation(value = "乘客微信授权", notes = "乘客微信授权")
    @RequestMapping(value = {"/wx/access/token"}, method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public ResponseData<Map<String, Object>> access(
            @ApiParam(name = "code", value = "code", required = true) @RequestParam String code,
            @ApiParam(name = "appid", value = "APP标识", required = true) @RequestParam String appid,
            HttpServletRequest request) {
        //判断token是否为空
        if (StringUtils.isEmpty(code)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "code不能为空", null);
        }
        HttpSession session = request.getSession();
        Object openid = session.getAttribute("openid");
        String mobile = "";
        String token = "";
        if (openid == null) {
            Map responseMap = getUserAccessToken(code);
            if (responseMap.containsKey(MagicConstant.PARAMS_OPENID)) {
                openid = responseMap.get("openid");
            } else {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取微信openid失败，原因：" + responseMap.get("errmsg"));
            }
        }

        //查询是否绑定手机
        Map<String, Object> map = MapUtils.build();
        map.put("openId", openid);
        PassengerDto passengerDto = passengerService.get(map).getData();
        if (passengerDto != null) {
            mobile = passengerDto.getMobile();
            token = passengerDto.getToken();
            if (StringUtils.isEmpty(token)) {
                PassengerDto passengerDto1 = new PassengerDto();
                passengerDto1.setUuid(passengerDto.getUuid());
                token = StringUtils.buildUUID();
                passengerDto1.setUuid(passengerDto.getUuid());
                passengerDto1.setToken(token);
                passengerService.edit(passengerDto1);
            }
        }
        map.clear();
        map.put("mobile", mobile);
        map.put("token", token);
        map.put("openId", openid);
        return ResponseData.buildSuccessResponse("获取成功", map);
    }

    public static Map getUserAccessToken(String code) {
        String requestUrl = user_access_token_url.replace("APPID", "wx7bef0a842666b7fa").replace("APPSECRET", "792e001755ce49e2c67aed366168d7b3").replace("CODE", code);
        String responseString = HttpUtils.getResponseString(requestUrl);
        try {
            return JsonUtils.readValue(responseString, Map.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return MapUtils.build();
    }

    @ApiOperation(value = "小程序乘客登陆凭证校验", notes = "微信接口请求错误则返回失败；成功则返回appid、session_key；若有对应的绑定用户，则同时返回用户信息", response = ResponseData.class)
    @RequestMapping(value = {"/login/wx/applet/verify"}, method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public ResponseData login(
            @ApiParam(name = "appid", value = "APP标识", required = true) @RequestParam String appid,
            @ApiParam(name = "code", value = "code", required = true) @RequestParam String code) throws IOException {

        //判断code是否为空
        if (StringUtils.isEmpty(code)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "code不能为空", null);
        }
        String url = "https://api.weixin.qq.com/sns/jscode2session?appid=" + WxConstants.WX_APPLET_APPID +
                "&secret=" + WxConstants.WX_APPLET_APPSECRET + "&js_code=" + code + "&grant_type=authorization_code";
        String responseStr = HttpUtils.getResponseString(url);
        logger.info("appid:{},code:{}, responseStr:{}", WxConstants.WX_APPLET_APPID, code, responseStr);
        if (StringUtils.isEmpty(responseStr)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "登陆凭证接口请求异常");
        }
        JsonNode jsonNode = JsonUtils.readNode(responseStr);
        if (jsonNode.get("errcode") != null) {
            return ResponseData.buildErrorResponse(jsonNode.get("errcode").asInt(0), jsonNode.get("errmsg").asText());
        }
        String openid = jsonNode.get("openid").asText();
        //查询绑定用户
        Map<String, Object> result = MapUtils.build();
        result.put("openid", openid);
        PassengerDto passenger = passengerService.get(MapUtils.build("openId", openid)).getData();
        if (passenger != null) {
            //模拟登陆操作
            passenger.setActive(1);
            ResponseData<PassengerVo> login = passengerService.login(passenger, new PassengerLogDto());
            if (login.isSuccess()) {
                result.put("user", login.getData());
            }
        }
        return ResponseData.buildSuccessResponse("成功获取绑定用户", result);
    }
}
